/**
 ****************************************************************************
 * Copyright (C) Marcelo F. Ochoa. All rights reserved.                      *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 */

package com.prism.oracle;

import java.io.IOException;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;

import javax.servlet.http.HttpServletRequest;

import oracle.lite.poljdbc.OracleCallableStatement;
import oracle.lite.poljdbc.OracleResultSet;

import org.apache.log4j.Logger;

import com.prism.DBConnection;
import com.prism.DownloadRequest;


/**
 * This class implements a ConcreteProduct class of abtract factory patterm.
 * Define a product object (DownloadLite represent a Download request) to be created by the corresponding concrete factory.
 * Implements the AbstractProduct Interface (DownloadRequest)
 */
public class DownloadLite extends DownloadRequest {
    private static Logger log = Logger.getLogger(DownloadLite.class);
    
    public DownloadLite() { };

    public DownloadLite(HttpServletRequest request, DBConnection repositoryConnection)
        throws IOException, SQLException {
            super(request, repositoryConnection);
    }

    /** Create a concrete DownloadRequest (DownloadLite). */
    public DownloadRequest create(HttpServletRequest request, DBConnection repositoryConnection)
        throws IOException, SQLException {
            return new DownloadLite(request, repositoryConnection);
    }

    private String matchCase(String str) {
        DBConnJava connJava = (DBConnJava)conn;
        if (connJava.caseSensity.equalsIgnoreCase("lower"))
            return str.toLowerCase();
        else if (connJava.caseSensity.equalsIgnoreCase("upper"))
            return str.toUpperCase();
        else
            return str;
    }

    /**
     * @return true if there is a file for downloading
     * if there where errors return false and log.warn the exception message
     */
    public boolean isFileDownload() {
       CallableStatement cs = null;
       int i;
        try {
            cs = conn.sqlconn.prepareCall("{ ? = call JwpgDocLoad.ISFILEDOWNLOAD() }");
            cs.registerOutParameter(1, Types.INTEGER);
            cs.execute();
            i = cs.getInt(1);
            cs.close();
        } catch (SQLException e) {
            log.warn(".isFileDownload exception when calling wpg_docload.is_file_download",e);  
            i=0; 
        } finally {
            try {
              cs.close();
            } catch (SQLException e) {
              log.warn(".isFileDownload exception when closing callable statement",e);  
            } finally {
              cs = null;  
            }
        }
       return (i!=0); 
    }
    
    public InputStream getStream(String downloadInfo) throws SQLException {
        InputStream in = null;
        int i, length;
        String mime = "application/octet-stream";
        java.sql.Date lastUpdated = new java.sql.Date(System.currentTimeMillis());
        CallableStatement cs = null;
        // Get generated page in one call via stream
        if (downloadInfo.startsWith("Error:"))
            throw new SQLException("DBPrism - DonwloadLite Adapter JwpgDocLoad.getDownloadFile " + downloadInfo);
        if ("B".equalsIgnoreCase(downloadInfo)) {
            oracle.lite.poljdbc.BLOB locator = null;
            // Handle download file as BLOB
            cs = conn.sqlconn.prepareCall(" ? = call JwpgDocLoad.GETCONTENTLENGTH() }");
            cs.registerOutParameter(1, Types.INTEGER);
            cs.execute();
            length = cs.getInt(1);
            cs.close();
            cs = conn.sqlconn.prepareCall("{ ? = call JwpgDocLoad.GETDOWNLOADBLOB() }");
            cs.registerOutParameter(1, Types.LONGVARBINARY);
            cs.execute();
            locator = (oracle.lite.poljdbc.BLOB) ((OracleCallableStatement)cs).getBlob(1);
            in = locator.getBinaryStream();
            cs.close();
        } else {
            oracle.lite.poljdbc.BLOB locator = null;
            i = Integer.parseInt(downloadInfo.substring(0, downloadInfo.indexOf('X')));
            String name = downloadInfo.substring(downloadInfo.indexOf('X') + 1, downloadInfo.indexOf('X') + i + 1);
            // Create a Statement
            Statement stmt = conn.sqlconn.createStatement();
            // Select the lobs
            ResultSet rset = stmt.executeQuery("select mime_type,doc_size,last_updated,blob_content from " +
                conn.connInfo.documentTable + " where name = '" + name + "'");
            if (rset.next()) {
                mime = rset.getString(1);
                length = rset.getInt(2);
                lastUpdated = rset.getDate(3);
                locator = ((OracleResultSet)rset).getBLOB(4);
                in = locator.getBinaryStream();
            } else {
                // nothing here ?
                rset.close();
                stmt.close();
                rset = null;
                stmt = null;
                throw new SQLException("DBPrism - DonwloadLite Adapter: can't get download file: " + name);
            }
            rset.close();
            stmt.close();
        }
        // Caller will use these values
        this.setContentLength(length);
        this.setContentType(mime);
        // Round Last modified date to seconds, discard mili-seconds
        this.setLastModified(lastUpdated.getTime() / 1000 * 1000);
        return in;
    }
    /**
     * @return an encoded string with the download information
     * @see com.prism.DownloadRequest#getDownloadInfo
     */
    public String getDownloadInfo() {
        CallableStatement cs = null;
        String downloadInfo = "";
         try {
             cs = conn.sqlconn.prepareCall("{ ? = call JwpgDocLoad.GETDOWNLOADFILE() }");
             cs.registerOutParameter(1, Types.VARCHAR);
             cs.execute();
             downloadInfo = cs.getString(1);
             cs.close();
         } catch (SQLException e) {
             log.warn(".getDownloadInfo exception when calling JwpgDocLoad.GETDOWNLOADFILE()",e);  
             downloadInfo=""; 
         } finally {
             try {
               cs.close();
             } catch (SQLException e) {
               log.warn(".getDownloadInfo exception when closing callable statement",e);  
             } finally {
               cs = null;  
             }
         }
        return downloadInfo; 
    }

    /**
     * @see com.prism.DownloadRequest#callAccessProcedure
     * @throws SQLException
     */
    public void callAccessProcedure() throws SQLException {
        CallableStatement cs = null;
         try {
             cs =
                 conn.sqlconn.prepareCall("{ call " + conn.connInfo.docAccessProcedure +
                                           "() }");
             cs.execute();
             cs.close();
         } catch (SQLException e) {
             log.warn(".getDownloadInfo exception when calling '"+conn.connInfo.docAccessProcedure+"' procedure",e);
             throw e;
         } finally {
             try {
               cs.close();
             } catch (SQLException e) {
               log.warn(".getDownloadInfo exception when closing callable statement",e);  
             } finally {
               cs = null;  
             }
         }
    }
}
